/**
 *    @file       message.h
 *
 *    @brief      
 *    @details
 *
 *    @version    1.0
 *    @date       02/10/2014 05:51:17 PM
 *
 *    @author     Theophilus (), wangtf418@gmail.com
 */
#ifndef _SF_MESSAGE_H_
#define _SF_MESSAGE_H_
#include <netinet/in.h>
#include "srvdef.h"
#include "argument.h"

struct msghead
{
	bf_uint32_t m_thd_type;
	bf_uint32_t m_thd_index;
	bf_uint64_t m_tsk_id;

	bf_uint32_t m_src_thd_type;
	bf_uint32_t m_src_thd_index;
	bf_uint64_t m_src_tsk_id;

	bf_uint32_t m_msgtype;

	msghead() : m_thd_type(0), m_thd_index(0), m_tsk_id(0),
		m_src_thd_type(0), m_src_thd_index(0), m_src_tsk_id(0),
		m_msgtype(0)
	{

	}

	msghead(const msghead &head)
	{
		memcpy(this, &head, sizeof(head));
	}
};

class msgbody
{
public:
	msgbody() {}
	virtual ~msgbody() {}
};

class message
{
public:
	message(msghead &head, msgbody *body)
		: m_msghead(head), m_msgbody(body)
	{

	}

	~message()
	{
		if (m_msgbody)
		{
			delete m_msgbody;
		}
	}

public:
	inline msghead & get_msghead() {return m_msghead;}
	inline msgbody * get_msgbody() {return m_msgbody;}
	inline void set_msgbody(msgbody *body) {m_msgbody = body;}

	inline void free_msgbody()
	{
		if (m_msgbody)
		{
			delete m_msgbody;
			m_msgbody = NULL;
		}
	}

private:
	msghead m_msghead;
	msgbody *m_msgbody;
};

template<typename _Tinfo>
class simplemsgbody : public msgbody
{
public:
	simplemsgbody(const _Tinfo &info)
	{
		memcpy(&m_info, &info, sizeof(m_info));
	}

public:
	inline _Tinfo & get_info() {return m_info;}

private:	
	_Tinfo m_info;
};

template<typename _Tinfo>
class commsgbody : public msgbody
{
public:
	commsgbody(_Tinfo *info)
		: m_info(info)
	{

	}

	~commsgbody()
	{
		if (m_info)
		{
			delete m_info;
		}
	}

public:
	inline _Tinfo * get_info() {return m_info;}
	inline void detach_info() {m_info = NULL;}

private:	
	_Tinfo *m_info;
};

class bufmsgbody : public msgbody
{
public:
	bufmsgbody(bf_char_t *buf, bf_size_t buflen)
		: m_buf(buf), m_buflen(buflen)
	{

	}

	virtual ~bufmsgbody()
	{
		if (m_buf)
		{
			delete [] m_buf;
		}
	}

public:
	inline bf_char_t * get_buf() {return m_buf;}
	inline bf_size_t get_buflen() {return m_buflen;}

	inline void detach_buf()
	{
		m_buf = NULL;
		m_buflen = 0;
	}

protected:
	bf_char_t *m_buf;
	bf_size_t m_buflen;
};

class addr_bufmsgbody : public bufmsgbody
{
public:
	addr_bufmsgbody(bf_char_t *buf, bf_size_t buflen, struct sockaddr_in &addr)
		: bufmsgbody(buf, buflen)
	{
		memcpy(&m_addr, &addr, sizeof(m_addr));
	}

public:
	struct sockaddr_in & get_addr() {return m_addr;}

protected:
	struct sockaddr_in m_addr;
};

class client_bufmsgbody : public bufmsgbody
{
public:
	client_bufmsgbody(bf_char_t *buf, bf_size_t buflen, bf_uint_t srvip, bf_ushort_t srvport, bf_uint_t seq_num)
		: bufmsgbody(buf, buflen), m_srvip(srvip), m_srvport(srvport), m_sequence_num(seq_num)
	{

	}

	inline bf_uint_t get_srvip() {return m_srvip;}
	inline bf_ushort_t get_srvport() {return m_srvport;}
	inline bf_uint_t get_sequence_num() {return m_sequence_num;}

protected:
	bf_uint_t m_srvip;	
	bf_ushort_t m_srvport;
	bf_uint_t m_sequence_num;
};

class clientres_bufmsgbody : public bufmsgbody
{
public:
	clientres_bufmsgbody(bf_char_t *buf, bf_size_t buflen, bf_int_t result, bf_uint_t seq_num)
		: bufmsgbody(buf, buflen), m_result(result), m_sequence_num(seq_num)
	{

	}

	inline bf_ushort_t get_result() {return m_result;}
	inline bf_uint_t get_sequence_num() {return m_sequence_num;}

protected:
	bf_int_t m_result;
	bf_uint_t m_sequence_num;
};

class send_message
{
public:
	send_message(bf_char_t *buf, bf_size_t buflen)
		: m_buf(buf), m_buflen(buflen), m_cur_sendlen(0)
	{

	}

	~send_message()
	{
		if (m_buf)
		{
			delete [] m_buf;
		}
	}

public:
	inline bf_char_t * get_buf() {return m_buf;}
	inline bf_size_t get_buflen() {return m_buflen;}
	inline bf_size_t get_cur_sendlen() {return m_cur_sendlen;}
	inline void set_cur_sendlen(bf_size_t cur_sendlen) {m_cur_sendlen = cur_sendlen;}

protected:
	bf_char_t *m_buf;
	bf_size_t m_buflen;
	bf_size_t m_cur_sendlen;
};

template<typename _Tinfo>
class simple_send_message : public send_message
{
public:
	simple_send_message(bf_char_t *buf, bf_size_t buflen, _Tinfo &info)
		: send_message(buf, buflen)
	{
		memcpy(&m_info, &info, sizeof(m_info));
	}

public:
	inline _Tinfo & get_info() {return m_info;}

protected:
	_Tinfo m_info;
};

typedef simple_send_message<struct sockaddr_in> udp_send_message;

template<typename _Tinfo>
class com_send_message : public send_message
{
public:
	com_send_message(bf_char_t *buf, bf_size_t buflen, _Tinfo *info)
		: send_message(buf, buflen), m_info(info)
	{

	}

public:
	inline _Tinfo * get_info() {return m_info;}
	inline void detach_info() {m_info = NULL;}

protected:
	_Tinfo *m_info;
};

#endif

